package Element.Geom;

import java.awt.*;
import java.util.*;

import DistSys.Sys;
import Element.*;

public class ThreeNodeElemGeom extends AbsElemGeom implements Cloneable {

    boolean isSwitched;
    public int x3,y3, x3Stored, y3Stored;

    transient public Vector conn3;
    public Vector idConn3;
    transient public AbsElem parent2;

    public ThreeNodeElemGeom() {
      super();
      isSwitched=false;
      conn3 = new Vector(4,4);
      idConn3 = new Vector(4,4);
      parent2=null;
    }

    //overriden method
    public void initFromScreen(String n, Point pt){
        init(n);
        rotation =0; //by default it is initally horizontal
        setNode1FromScreen( pt );  //from screen
        findNode2BasedonDir(true); // default size
        calcFrame();
        findNode3BasedonScreen();
    }

    //overloaded method
    //init from DB
    public void initFromDB(String n, String desc, int r, int LTC,
                           boolean sn, boolean sd, int[][] si, Point pt1,
                           Point pt2,  boolean b) {
        init(n, desc, r, LTC, sn, sd, si);

        setNode1FromStored( pt1 );  //from stored
        setNode2FromStored( pt2 );
        findNode3BasedonScreen();
        calcFrame();
        isSwitched = b;
    }

    /*================================================
    getter methods
    ================================================*/
    public int getX3(){ return x3;}
    public int getY3(){ return y3;}

    public int getX3Stored(){ return x3Stored;}
    public int getY3Stored(){ return y3Stored;}


  //Find node 3 from node 1 and 2 based on (x1,y1) & (x2, y2) --[screen values]
  //First, get (x3, y3) ; then (x3Stored, y3Stored); lastly, sync (x3, y3) with
  //(x3Stored, y3Stored).
    public void findNode3BasedonScreen(){
        double ruo = Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
        double theta = Math.asin((y2-y1)/ruo);
        if( x2 >=x1 && y2>=y1 )     { /* do nothing, b/c in (0-90) */   }
        else if( x2>=x1 && y2<y1)   { /* do nothing, b/c in (0-90) */   }
        else if( x2<x1 && y2>=y1 )  { theta = Math.PI - theta;  }
        else /* (x2<x1 && y2<y1)*/  { theta = -Math.PI - theta; }

        theta = theta + Math.PI /4.0 ;  // node2 rotated for theta + 45 degree

        x3 = x1 + (int) ( ruo/ Math.sqrt(2) * Math.cos(theta));
        y3 = y1 + (int) ( ruo/ Math.sqrt(2) * Math.sin(theta));

        x3Stored = (int) Math.round (x3/Sys.prjInfo.dZoomFactor);
        y3Stored = (int) Math.round (y3/Sys.prjInfo.dZoomFactor);
        x3 = (int) Math.round( x3Stored * Sys.prjInfo.dZoomFactor );
        y3 = (int) Math.round( y3Stored * Sys.prjInfo.dZoomFactor );
    }


    public boolean getIsSwitched(){ return isSwitched;}
    public void    setIsSwitched(boolean b){ isSwitched=b;}

    //overridden methods
    public void incRotate(){  // rename it to rotateElem
        rotation ++;
        rotation %=4;
        findNode2BasedonDir(false); // no default size
        findNode3BasedonScreen();
        calcFrame();
    }

    public void scaleCoord(double s){
        super.scaleCoord( s );
        x3=(int) Math.round(((double) x3Stored) * s);
        y3=(int) Math.round(((double) y3Stored) * s);
    }

    public void toggle() {
        if( isSwitched ) isSwitched = false;
        else isSwitched = true;
    }

    //not a real implementation; real implementation is in the inner class of elements
    //public void draw(Graphics g){}

    public Object clone(){
        ThreeNodeElemGeom created = new ThreeNodeElemGeom();
        // all ref. in created has been instantiated such as frame, conn1,conn2, childList

        this.copyTo( created);// copy AbsElemGeom attributes to created

        //ThreeNodeElemGeom's own data
        created.isSwitched = this.isSwitched;
        created.findNode3BasedonScreen(); //find node 3 from nodes 1 and 2
        //no need to copy contents in conn3 since created.conn3 should be null.

        return created;
    }

    public void displace(int dx, int dy){
        super.displace( dx, dy);  //calcFrame called here
        findNode3BasedonScreen();
        //this.calcFrame(); //no need for this
    }
}

//Trash Code -- May be useful in the future.  Don't delete now.
    //for screen drawing
    //private void findNode3BadedonDir(){
    //    int dftHalfDist =2; //vertical/horizontal distance between Node1 and Node 3.
    //                        // in findNode2BasedonDir(), dftDist =4;
    //    switch (rotation%4) {
    //        case 0: x3Stored = x1Stored + dftHalfDist; y3Stored = y1Stored + dftHalfDist;  break;
    //        case 1: x3Stored = x1Stored - dftHalfDist; y3Stored = y1Stored + dftHalfDist;  break;
    //        case 2: x3Stored = x1Stored - dftHalfDist; y3Stored = y1Stored - dftHalfDist;  break;
    //        case 3: x3Stored = x1Stored + dftHalfDist; y3Stored = y1Stored - dftHalfDist;  break;
    //        default:
    //            System.out.println("Error @ AbsElemGeom:findNode2BasedOnDir()");
    //            break;
    //        //furthor work: need to judge: out of drawing boundary?
    //    }
    //    x3 = (int) Math.round( x3Stored * Sys.prjInfo.dZoomFactor);
    //    y3 = (int) Math.round( y3Stored * Sys.prjInfo.dZoomFactor);
    //}

    /*=============================================
    setter methods
    =============================================*/
//    public void setNode3FromScreen( Point p){
//        setNode3FromScreen( p.x, p.y );
//    }
//
//    public void setNode3FromScreen( int i, int j){
//        x3Stored=(int) Math.round(((float)i)/Sys.prjInfo.dZoomFactor);
//        y3Stored=(int) Math.round(((float)j)/Sys.prjInfo.dZoomFactor);
//        x3 = (int) Math.round( x3Stored * Sys.prjInfo.dZoomFactor);
//        y3 = (int) Math.round( y3Stored * Sys.prjInfo.dZoomFactor);
//    }
//
//    private void setNode3FromStored( int i, int j){
//        x3Stored=i; y3Stored=j;
//        x3=(int) Math.round(((float)i) * Sys.prjInfo.dZoomFactor);
//        y3=(int) Math.round(((float)j) * Sys.prjInfo.dZoomFactor);
//    }
//
//    private void setNode3FromStored( Point p){
//        setNode3FromStored( p.x, p.y);
//    }

//    //find node 2 from the screen (XY) of node 1 and 3
//    private void findNode2BasedonScreen(){
//        double ruo = Math.sqrt( (x3-x1)*(x3-x1) + (y3-y1)*(y3-y1) );
//        double theta = Math.asin((y3-y1)/ruo);
//        if( x3 >=x1 && y3>=y1 )     { /* do nothing, b/c in (0-90) */   }
//        else if( x3>=x1 && y3<y1)   { /* do nothing, b/c in (0-90) */   }
//        else if( x3<x1 && y3>=y1 )  { theta = Math.PI - theta;  }
//        else /* (x3<x1 && y3<y1)*/  { theta = -Math.PI - theta; }
//
//        theta = theta - Math.PI /4.0 ;  // node3 rotated theta - 45 degree
//
//        x2 = x1 + (int) ( ruo* Math.sqrt(2) * Math.cos(theta) );
//        y2 = y1 + (int) ( ruo* Math.sqrt(2) * Math.sin(theta));
//
//        x2Stored = (int) Math.round(x2/Sys.prjInfo.dZoomFactor);
//        y2Stored = (int) Math.round(y2/Sys.prjInfo.dZoomFactor);
//        x2=(int) Math.round( x2Stored * Sys.prjInfo.dZoomFactor);
//        y2=(int) Math.round( y2Stored * Sys.prjInfo.dZoomFactor);
//    }